﻿/*------------------------------------------------------------------------

CXXLXMLCOMPOSITE.HPP v3.1

Copyright 楊志賢 CxxlMan, 2011 - 2012
All Rights Reserved


------------------------------------------------------------------------*/

#if !defined(__CXXLXMLCOMPOSITE_HPP_CxxlMan)
#define __CXXLXMLCOMPOSITE_HPP_CxxlMan

#include "CXXLCOMPOSITE.HPP"
#include "DLLDEF.HPP"

#if defined(_CXXLCONTAINER_DLLEXPORT)
#define CXXLCONTAINER_DLLEXPORT CXXL_DLLEXPORT
#else
#define CXXLCONTAINER_DLLEXPORT CXXL_DLLIMPORT
#endif


namespace CxxlMan
{

class CXXLCONTAINER_DLLEXPORT cxxlXml_Node;
class CXXLCONTAINER_DLLEXPORT cxxlXml_Content;

struct XmlAttr_li:virtual public cxxlObject
{
  XmlAttr_li()
    :cxxlObject(Spirit_Easy)
  {}
  UNICODE_String Name;
  UNICODE_String Attr;
};

// cxxlXml_Node 和 cxxlXml_Content 的父類別，
// 只含 Attr
//
// 使用 protected 繼承沒法用 dynamic_cast 從 cxxlComposite 轉形到 cxxlXmlComposite，只好用強制轉形
//class CXXLCONTAINER_DLLEXPORT cxxlXmlComposite:public cxxlComposite<cxxlComposite<string_wrapper<wchar_t>,true>,false>

class CXXLCONTAINER_DLLEXPORT cxxlXmlComposite:protected cxxlComposite<cxxlComposite<string_wrapper<wchar_t>,true>,false>
{
protected:

  // Constructor
  cxxlXmlComposite(const UNICODE_String &idName, ISpirit *spirit);

public:

  // Destructor
  virtual ~cxxlXmlComposite(){}

  // 設定屬性值
  void cxxlFASTCALL SetAttr(const UNICODE_String &Value, const UNICODE_String &Name);

  // 取得屬性值，若不存在回覆空物件，可用 Smart_Ptr::isNULL() 檢查
  UNICODE_String cxxlFASTCALL GetAttr(const UNICODE_String &Name) const;

  // 取得所有屬性列表
  Smart_Ptr<cxxlList<XmlAttr_li> > cxxlFASTCALL GetAttrList() const;

  // 取得這個節點的名稱
  UNICODE_String cxxlFASTCALL GetName() const;

  // 轉換類別，若不行回覆 NULL
  virtual Smart_Ptr<cxxlXml_Node> cxxlFASTCALL ConvertToNode();
  virtual Smart_Ptr<cxxlXml_Content> cxxlFASTCALL ConvertToContent();

  friend class Smart_Ptr<cxxlXmlComposite>;

};

// 葉節點，只含一個 Content 文字內容
class CXXLCONTAINER_DLLEXPORT cxxlXml_Content:public cxxlXmlComposite
{
  UNICODE_String m_Content;

  virtual Smart_Ptr<cxxlXml_Content> cxxlFASTCALL ConvertToContent();

  // Constructor
  cxxlXml_Content(const UNICODE_String &idName, ISpirit *spirit);

public:

  // Destructor
  virtual ~cxxlXml_Content(){};

  void cxxlFASTCALL SetContent(const UNICODE_String &Content);
  UNICODE_String cxxlFASTCALL GetContent() const;

  friend class Smart_Ptr<cxxlXml_Content>;
  friend class cxxlXml_Node;
};

// 技節點，不含 Content 文字內容，含多個 cxxlXmlComposite 和操作
class CXXLCONTAINER_DLLEXPORT cxxlXml_Node:public cxxlXmlComposite
{

  cxxlXmlComposite *pcxxlXmlComposite; // For  cxxlComposite::CreateSelf()

  // 建立新子節點時用來產生延伸類別的物件
  // 所以延伸別必須覆載
  // 改寫自 cxxlComposite
  virtual cxxlXmlComposite * cxxlFASTCALL CreateSelf(UNICODE_String idName,ISpirit *spirit) const;

  virtual Smart_Ptr<cxxlXml_Node> cxxlFASTCALL ConvertToNode();

public:
  // Constructor
  cxxlXml_Node(const UNICODE_String &idName, ISpirit *spirit = Spirit_Easy);

  // Destructor
  virtual ~cxxlXml_Node(){};

  // 取得父節點
  Smart_Ptr<cxxlXml_Node> cxxlFASTCALL GetParent() const;

  // 取得所有子節點列表
  Smart_Ptr<cxxlList<cxxlXmlComposite> > cxxlFASTCALL GetSubnodes() const;

  // 增加一個子節點，名稱不能空
  Smart_Ptr<cxxlXml_Node> cxxlFASTCALL AddNode(const UNICODE_String &Name);
  // Node 須是其子節點，名稱不能空
  Smart_Ptr<cxxlXml_Node> cxxlFASTCALL AddPrevNode(const UNICODE_String &Name, const Smart_Ptr<cxxlXmlComposite> &Node);
  Smart_Ptr<cxxlXml_Node> cxxlFASTCALL AddNextNode(const UNICODE_String &Name, const Smart_Ptr<cxxlXmlComposite> &Node);

  // 增加一個內容葉節點，名稱可空
  Smart_Ptr<cxxlXml_Content> cxxlFASTCALL AddContent(const UNICODE_String &Name);
  // Node 須是其子節點，名稱可空
  Smart_Ptr<cxxlXml_Content> cxxlFASTCALL AddPrevContent(const UNICODE_String &Name, const Smart_Ptr<cxxlXmlComposite> &Node);
  Smart_Ptr<cxxlXml_Content> cxxlFASTCALL AddNextContent(const UNICODE_String &Name, const Smart_Ptr<cxxlXmlComposite> &Node);

  friend class Smart_Ptr<cxxlXml_Node>;

};

// 將 XML_Node 匯出到 XmlStr
extern CXXLCONTAINER_DLLEXPORT void cxxlFASTCALL ExportXML(std::wostream &XmlStr, const Smart_Ptr<cxxlXml_Node> &XML_Node);

// 由 XmlStr 匯入建立 XML 容器傳回
// 若失敗傳回 NULL
// spirit 是建立 XML 容器用的
extern CXXLCONTAINER_DLLEXPORT Smart_Ptr<cxxlXml_Node> cxxlFASTCALL ImportXML(std::wistream &XmlStr, ISpirit *spirit = Spirit_Easy);


}   /* namespace CxxlMan */
#endif

